use iced::{Application, Command, Element, Subscription, executor};

mod consts;
mod styles;
mod recv;
mod login;
mod chat;
mod cmd;


use login::Login;
use chat::Chat;
use moyu_chat_core::{client::Client, utils};

pub enum Screen {
    Login,
    Chat,
}

impl Default for Screen {
    fn default() -> Self {
        Self::Login
    }
}

pub enum ScreenState {
    Keep,
    SwitchTo(Screen, String),
    Exit,
}

#[derive(Default)]
pub struct ChatUI {  
    should_exit: bool,
    
    state: Screen,
    login: Login,
    chat: Chat,
}

#[derive(Debug)]
pub enum Message {
    LoginMessage(login::Message),
    ChatMessage(chat::Message)
}

impl Application for ChatUI {
    type Executor = executor::Default;

    type Message = Message;

    type Flags = ();

    fn new(_flags: Self::Flags) -> (Self, iced::Command<Self::Message>) {
        (Self {
            should_exit: false,
            chat: Chat::new(utils::new_local_addr().to_string()),
            login: Login::new(),
            ..Default::default()
        }, Command::none())
    }

    fn should_exit(&self) -> bool {
        self.should_exit
    }

    fn title(&self) -> String {
        match self.state {
            Screen::Login => self.login.title(),
            Screen::Chat => self.chat.title()
        }
    }

    fn subscription(&self) -> Subscription<Self::Message> {
        if self.should_exit {
            return Subscription::none();
        }
        match self.state {
            Screen::Chat => self.chat.subscription().map(Message::ChatMessage),
            _ => Subscription::none(),
        }
    }

    fn update(
        &mut self,
        message: Self::Message,
        _clipboard: &mut iced::Clipboard,
    ) -> iced::Command<Self::Message> {
        match message {
            Message::LoginMessage(msg) => {
                if let ScreenState::SwitchTo(screen, name) = self.login.update(msg) {
                    self.state = screen;
                    self.chat.set_client(Client::from_addr(name, self.chat.recv_addr()));
                }
            }
            Message::ChatMessage(msg) => {
                match self.chat.update(msg) {
                    ScreenState::Exit => self.should_exit = true,
                    _ => ()
                }
            },
        }
        Command::none()
    }

    fn view(&mut self) -> Element<'_, Self::Message> {
        match self.state {
            Screen::Login => self.login.view().map(Message::LoginMessage),
            Screen::Chat => self.chat.view().map(Message::ChatMessage)
        }
    }
}